/**
* Oxide
*
* Copyright (c) 2011 Dinosaur Kick Pty Ltd, All rights reserved.
*
* This source code is made available under the "Modified BSD" licensing arrangement.
* See license.txt for details.
*/
// ----------------------------------------------------------------------------

class_decl_ptr parse_class(void)
{
	assert(m_cursor->identity == TOK_CLASS);
	
	class_decl_ptr class_ = boost::make_shared<class_decl_type>();
	class_->doc_block = m_cursor.incrementer().doc_block;

	m_cursor.advance();
	
	// Parse the class flags ...
	class_->is_abstract = parse_flag(TOK_ABSTRACT);
	class_->is_final = parse_flag(TOK_FINAL);

	// Read the class name ...
	if (!parse_list(TOK_IDENTIFIER, TOK_DOT, TOK_OPEN_BRACE, class_->namespace_atoms))
	{
		m_cursor.advance_to(TOK_OPEN_BRACE);
	}
	else if (class_->namespace_atoms.size() < 2)
	{
		error
		(
			O2_FORMAT("Class %s must have a namespace name.")
				% class_->name
		);
	}

	class_->name = class_->namespace_atoms.back();
	class_->namespace_atoms.pop_back();

	// Parse the class body ...
	if (m_cursor->identity != TOK_OPEN_BRACE)
	{
		unexpected_token_error(TOK_OPEN_BRACE);
		return class_;
	}
	
	m_cursor.next();

	while (m_cursor.skip_empty())
	{
		if (m_cursor->identity == TOK_ACCESS_MODIFIER)
		{
			class_member_ptr member = parse_class_member();
			if (member)
			{
				if (class_->has_member(member->name))
				{
					error
					(
						O2_FORMAT("Class %s already contains a member named '%s'.")
							% class_->name
							% member->name
					);
				}
				else
				{
					class_->members[member->name] = member;
				}
			}
			else
			{
				m_cursor.advance_to(TOK_ACCESS_MODIFIER, TOK_CLOSE_BRACE);
			}
		}
		else if (m_cursor->identity == TOK_CLOSE_BRACE)
		{
			m_cursor.advance();
			break;
		}
		else
		{
			unexpected_token_error(TOK_ACCESS_MODIFIER, TOK_CLOSE_BRACE);
			if (!m_cursor.advance_to(TOK_ACCESS_MODIFIER, TOK_CLOSE_BRACE))
			{
				break;
			}
		}
	}

	return class_;
}

// ----------------------------------------------------------------------------
